package mapspinner;

import java.io.Serializable;

import com.jme.math.FastMath;

/**
 * A positional key that properly calculates its hashCode to allow for
 * 65535x65535 possible terrain blocks to exist.
 * 
 * @author James Vos
 */
public class TerrainKey implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8461847703703192453L;

	public short x, z;

	/**
	 * Construct this key from a hashcode of another key
	 * 
	 * @param hashCode
	 *            the hashcode to use.
	 */
	public TerrainKey(final int hashCode) {
		x = (short) (hashCode & 0x0000FFFF);
		z = (short) Integer.rotateRight(hashCode & 0xFFFF0000, 16);
	}

	/**
	 * Construct a key from x and y positions.
	 * 
	 * @param x
	 *            the x position
	 * @param y
	 *            the y position
	 */
	public TerrainKey(final short x, final short y) {
		this.x = x;
		z = y;
	}

	/**
	 * Construct this key from another key.
	 * 
	 * @param key
	 *            the key to clone.
	 */
	public TerrainKey(final TerrainKey key) {
		x = key.x;
		z = key.z;
	}

	/**
	 * Calculate distance in keys
	 * 
	 * @param from
	 *            the other key to compare the distance from
	 * @return the distance between this key and the arguement
	 */
	public int distance(final TerrainKey from) {
		final int dx = x - from.x;
		final int dy = z - from.z;
		return (int) FastMath.sqrt(dx * dx + dy * dy);
	}

	/**
	 * check if this key matches another.
	 * 
	 * @param o
	 *            the other object to match it to.
	 */
	@Override
	public boolean equals(final Object o) {
		if (o instanceof TerrainKey) {
			final TerrainKey input = (TerrainKey) o;
			if (x == input.x)
				if (z == input.z)
					return true;
		}
		return false;
	}

	/**
	 * Generate a hashCode for this key
	 * 
	 * @return the hashCode generated.
	 */
	@Override
	public int hashCode() {
		return x & 0x0000ffff | z << 16 & 0xffff0000;
	}

	/**
	 * String conversion is this case displays some usefull data of this key.
	 * 
	 * @return some useful data.
	 */
	@Override
	public String toString() {
		return "Key: X=" + x + " Y=" + z + " Hashcode as bin="
				+ Integer.toBinaryString(hashCode());
	}
}
